/**
 * jQuery图片预览（文件）上传插件imageUpload
 * 
 * 作者（author）   ：Hypo Fan <hanbei20@vip.qq.com>
 * 
 * 版本（version）  ：1.0.0
 * 
 * 定义：
 * 1、$.fn.imageUpload(options)
 * 参数：
 * options          object          插件选项，可选
 * 2、$.imageUpload(element, options)
 * 参数：
 * element          string|object   文件表单选择器或者文件表单的jQuery对象，必选
 * options          object          插件选项，可选
 * 
 * 使用方法：
 * 1、$('文件表单选择器').imageUpload(options);
 * 2、$.imageUpload('文件表单选择器', options);
 * 3、$.imageUpload($('文件表单选择器'), options);
 * 
 * 选项：
 * autoUpload       boolean
 *                  是否自动上传，默认：false
 * uploadUrl        string
 *                  上传地址，如果autoUpload设置为true，则必填，如果为空，不上传
 * dataType         string
 *                  上传响应格式，默认：json
 * uploadName       string
 *                  上传表单文件键名，默认imageUploadFile
 * extends          object
 *                  表单扩展，json对象，与文件一起提交
 * beforeUpload     function(imageUpload)
 *                  上传前处理函数，默认为空，会传入当前imageUpload对象
 * upload           function(imageUpload)
 *                  上传函数，默认通过jQuery的ajax上传，需要浏览器支持FormData。如果覆盖，会传入当前imageUpload对象
 * success          function
 *                  上传成功函数，同$.ajax的success，默认为空，在覆盖upload时无效
 * error            function
 *                  上传失败函数，同$.error，默认为空，在覆盖upload时无效
 * afterUpload      function
 *                  上传完成函数，同$.ajax的complete，默认为空，不论上传成功或者失败都会执行，在覆盖upload时无效
 * beforePreview    function(imageUpload)
 *                  预览前处理函数，默认为空，会传入当前imageUpload对象
 * preview          string|object|function(imageUpload)
 *                  显示图片的img选择器或者jQuery对象，或者预览函数
 *                  如果为空，默认将图片预览显示到ID为“file表单的ID+'_preview'”的img上，如果没有，则创建一个img插入到file表单后面
 *                  如果是函数，则覆盖默认的预览函数，会传入当前imageUpload对象
 * afterPreview     function(imageUpload)
 *                  预览后处理函数，默认为空，会传入当前imageUpload对象
 */
(function ($) {
    $.fn.imageUpload = function (options) {
        var _this = this;
        _this.defaults = {
            'autoUpload': false,
            'uploadUrl': '',
            'dataType': 'json',
            'uploadName': 'imageUploadFile',
            'extends' : null,
            'beforeUpload': null,
            'upload': null,
            'success': null,
            'error': null,
            'afterUpload': null,
            'beforePreview': null,
            'preview': '',
            'afterPreview': null
        };
        _this.options = {};
        _this.init = function (options) {
            if (_this.length > 1) {
                _this.each(function () {
                    $(this).imageUpload(options);
                });
                return;
            }
            _this.options = $.extend(_this.defaults, options);
            _this.initEvent();
            if (!_this.is('input[type="file"]')) {
                return;
            }
            _this.on('change', function () {
                _this.beforePreview(_this);
                _this.preview();
                _this.afterPreview(_this);
                if (_this.options.autoUpload) {
                    _this.beforeUpload(_this);
                    _this.upload();
                }
            });
        };
        _this.initEvent = function () {
            if (_this.options.beforePreview && typeof (_this.options.beforePreview) == 'function') {
                _this.beforePreview = _this.options.beforePreview;
            }
            if (_this.options.afterPreview && typeof (_this.options.afterPreview) == 'function') {
                _this.afterPreview = _this.options.afterPreview;
            }
            if (_this.options.beforeUpload && typeof (_this.options.beforeUpload) == 'function') {
                _this.beforeUpload = _this.options.beforeUpload;
            }
            if (_this.options.success && typeof (_this.options.success) == 'function') {
                _this.success = _this.options.success;
            }
            if (_this.options.error && typeof (_this.options.error) == 'function') {
                _this.error = _this.options.error;
            }
            if (_this.options.afterUpload && typeof (_this.options.afterUpload) == 'function') {
                _this.afterUpload = _this.options.afterUpload;
            }
        };
        _this.beforePreview = function (imageUpload) {};
        _this.preview = function () {
            var preview = _this.options.preview;
            var type = typeof (preview);
            if (type == 'string') {
                if (preview == '') {
                    preview = $('#' + _this.attr('id') + '_preview');
                } else {
                    preview = $(preview);
                }
            } else if (preview && type == 'function') {
                preview(_this);
                return;
            }
            if (preview.length < 1) {
                preview = $('<img class="imageUpload-preview">');
                preview.insertAfter(_this);
                _this.options.preview = preview;
            }
            var file = _this.get(0).files[0];
            if (!file || !/image\/\w+/.test(file.type)) {
                preview.attr('src', '');
                return;
            }
            if (window.FileReader) {
                var fr = new FileReader();
                fr.readAsDataURL(file);
                fr.onloadend = function (e) {
                    preview.prop('src', e.target.result);
                };
            } else {
                var url = null;
                if (window.createObjectURL != undefined) {
                    url = window.createObjectURL(file)
                } else if (window.URL != undefined) {
                    url = window.URL.createObjectURL(file)
                } else if (window.webkitURL != undefined) {
                    url = window.webkitURL.createObjectURL(file)
                }
                preview.attr('src', url);
            }
            return _this;
        };
        _this.afterPreview = function (imageUpload) {};
        _this.beforeUpload = function (imageUpload) {};
        _this.upload = function () {
            if (!_this.options.autoUpload) {
                _this.beforeUpload(_this);
            }
            if (_this.options.upload && typeof (_this.options.upload) == 'function') {
                _this.options.upload(_this);
                return;
            }
            var file = _this.get(0).files[0];
            if (!file || !_this.options.uploadUrl) {
                return;
            }
            var data = new FormData();
            data.append(_this.options.uploadName, file);
            if (typeof(_this.options.extends) == 'object' && _this.options.extends.length > 0) {
                for (var key in _this.options.extends) {
                    var val = _this.options.extends[key];
                    data.append(key, val);
                }
            }
            $.ajax({
                'url': _this.options.uploadUrl,
                'type': 'POST',
                'data': data,
                'dataType': _this.options.dataType,
                'processData': false,
                'contentType': false,
                'cache': false,
                'success': function (Response) {
                    _this.success(Response);
                },
                'error': function (jqXHR, textStatus, errorThrown) {
                    _this.error(jqXHR, textStatus, errorThrown);
                },
                'complete': function (XMLHttpRequest, textStatus) {
                    _this.afterUpload(XMLHttpRequest, textStatus);
                }
            });
            return _this;
        };
        _this.success = function (Response) {};
        _this.error = function (jqXHR, textStatus, errorThrown) {};
        _this.afterUpload = function (XMLHttpRequest, textStatus) {};
        _this.init(options);
        return _this;
    };
    $.imageUpload = function (element, options) {
        var file = null;
        if (typeof (element) == 'string') {
            file = $(element);
        } else {
            file = element;
        }
        file.imageUpload(options);
    };
})(jQuery);